﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>

// 结构体/联合体(共用体)/枚举

// 结构体

//struct Stu
//{
//	char name[20];
//	char id[20];
//	int age;
//};
//
//int main()
//{
//	struct Stu s1 = { "张三","2023090640127",18 };
//	struct Stu s2 = { .age = 20,.id = "2023090640128",.name = "李四" };
//	printf("%s %s %d\n", s1.name, s1.id, s1.age);
//	printf("%s %s %d\n", s2.name, s2.id, s2.age);
//
//	return 0;
//}

//typedef struct S
//{
//	char name[20];
//	int age;
//}S;
//
//int main()
//{
//	S s1 = { "张三",18 };
//	S s2 = { .name = "李四",.age = 20 };
//		printf("%s %d\n", s1.name, s1.age);
//		printf("%s %d\n", s2.name, s2.age);
//	return 0;
//}


// 联合体

//union Un
//{
//	char c;
//	int i;
//};
//
//int main()
//{
//	union Un u = { 0 };
//	printf("%zd\n", sizeof(u));
//	return 0;
//}


//union Un
//{
//	char c;
//	int i;
//};
//
//int main()
//{
//	union Un u = { 0 };
//	printf("%p\n", &(u.i));
//	printf("%p\n", &(u.c));
//	printf("%p\n", &u);
//	return 0;
//}

//union Un
//{
//	char c;
//	int i;
//};
//
//int main()
//{
//	union Un u = { 0 };
//	u.i = 0x11223344;
//	u.c = 0x55;
//	printf("%x\n", u.i);
//	return 0;
//}

//union Un
//{
//	char c;
//	int i;
//};
//
//int main()
//{
//	union Un u = { 0 };
//	u.i = 1;
//	if (u.c == 1)
//	{
//		printf("小端\n");
//	}
//	else
//	{
//		printf("大端\n");
//	}
//	return 0;
//}



// 联合体大小的计算
//1.联合的⼤⼩⾄少是最⼤成员的⼤⼩。
//2.当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候，
//	就要对⻬到最⼤对⻬数的整数倍。
//union u1
//{
//	char c[7];
//	int i;
//}; // 8
//
//union u2
//{
//	int i;
//	char c[14];
//};// 16
//
//int main()
//{
//	printf("%zd\n", sizeof(union u1));
//	printf("%zd\n", sizeof(union u2));
//	return 0;
//}


//struct gift_list
//{
//	int stock_number; //库存
//	double price; //定价
//	int item_type; // 类型
//
//	union {
//		struct
//		{
//			char book_name[20];//书名
//			char author[20];//作者
//			int num_pages;//页数
//		}book;
//
//		struct
//		{
//			char design[30]; //设计
//		}mug;
//
//		struct
//		{
//			char design[30]; //设计
//			int colors; //颜色
//			int sizes; //尺寸
//		}shirt;
//	}item;
//};
//int check()
//{
//	union u
//	{
//		char c;
//		int i;
//	}u;
//	u.i = 1;
//	return u.c;
//}
//int main()
//{
//	int ret = check();
//	if (ret == 1)
//	{
//		printf("小端\n");
//	}
//	else
//	{
//		printf("大端\n");
//	}
//	return 0;
//}


// 枚举类型

//enum Sex
//{
//	MALE,// 0
//	FEMALE,// 1
//	SECRET// 2
//};
//
//enum Color
//{
//	RED, // 0
//	BULE,// 1
//	GREEN// 2
//};
//
//enum Book
//{
//	ZHAO_HUA,
//	KUANG_REN,
//	HONG_LOU_MENG
//};
//
//int main()
//{
//	int input = 0;
//	printf("请选择->");
//	scanf("%d", &input);
//	switch (input)
//	{
//	case ZHAO_HUA:
//
//		break;
//	case KUANG_REN:
//
//		break;
//	case HONG_LOU_MENG:
//
//		break;
//	}
//	return 0;
//}


// 动态内存的管理

// 1.我们为什么要有动态内存的分配

//首先我们来看下面的代码

//int main()
//{
//	int a = 10;
//	int arr[10] = { 0 };
//	return 0;
//}

//int类型的变量a向内存空间申请了4个字节，
//int[10]类型的数组在空间开辟了40个字节的空间

// 但是以上两种形式的空间开辟大小都是固定的
// 数组一旦确定了空间，指定了数组的长度，一般数组空间
// 大小就无法调整了

// 但是我们有时对空间的需求又是灵活的，打个比方，今天班级
// 内有35个同学，我们创建了char[35],但是后面如果这个班级
// 又再加入了新的同学或者走掉了一些同学呢？这种动态的变化
// 有时是无法避免的，因此在C语言中引入了动态内存开辟，让
// 我们可以自己申请和释放空间，可以更加灵活的控制程序

// 但是方便的同时也带来了隐患，我们同样需要注意

// malloc 和 free

// malloc 函数

// C语言提供的一个动态内存开辟函数：

// 这是它的原型：

//void* malloc(size_t size);

// void* - 返回类型

//size_t - 传入我们需要开辟空间的大小

// 这个函数会向内存申请一块连续可用的空间，
// 并且返回指向这块空间的指针

// 1. 开辟成功则会返回一个指向开辟好空间的地址

// 2. 开辟失败则会返回NULL指针，因此我们需要对返回值做
// 判断，然后执行我们接下来的指令

// 3. void* 的返回接受类型需要我们自己判定并创建接收

// 4. 如果参数size为0，则malloc的行为是标准未定义，则取决于编译器


// free 函数

// C语言提供的一种回收释放动态内存的函数

// 函数原型：

//void free(void* ptr);

// 1. 如果参数ptr指向的空间不是动态开辟的，则free函数的行为未定义

// 2. 如果参数ptr是NULL指针。则函数不执行

// 函数malloc和free都需要声明 #include <stdlib.h>

//int main()
//{
//	int num = 0;
//	scanf("%d", &num);
//	int arr[num] = { 0 };
//	int* ptr = NULL;
//	ptr = (int*)malloc(num * sizeof(int));
//	if (ptr != NULL)
//	{
//		int i = 0;
//		for (i = 0; i < num; i++)
//		{
//			*(ptr + i) = 0;
//		}
//	}
//	free(ptr);
//	ptr = NULL;
//	return 0;
//}

// 函数 calloc 和 realloc

// calloc函数

//作用：开辟num个字节的空间并且初始化为0

// calloc和malloc函数的差别只在于，一个初始化，一个没有初始化

//函数原型：

//void* calloc(size_t num, size_t size);
//
// 
//int main()
//{
//	int* p = (int*)calloc(10, sizeof(int));
//	if (NULL != p)
//	{
//		int i = 0;
//		for (i = 0; i < 10; i++)
//		{
//			printf("%d ", *(p + i));
//		}
//	}
//	free(p);


// realloc 函数

// 作用：realloc 函数可以使动态内存的管理更加的灵活
// 有时我们觉得申请的空间大了或者小了，但是realloc函数可以做到对
// 动态内存开辟空间的大小做调整

// 函数原型：

//void* realloc(void* ptr, size_t size);

// ptr 是需要调整的地址，调整完毕后返回调整后内存的起始地址

//这个函数调整原内存空间⼤⼩的基础上，
//还会将原来内存中的数据移动到新的空间

// size 是需要调整后的大小

//realloc在调整内存空间的是存在两种情况：
//◦ 情况1：原有空间之后有⾜够⼤的空间
//◦ 情况2：原有空间之后没有⾜够⼤的空间

//int main()
//{
//	int* ptr = (int*)malloc(5 * sizeof(int));
//	if (ptr != NULL)
//	{
//
//	}
//	else
//	{
//		perror("malloc");
//		return 1;
//	}
//
//	//ptr = (int*)realloc(ptr, 10 * sizeof(int));
//
//	int* p = NULL;
//	p = realloc(ptr, 10 * sizeof(int));
//	if (NULL != p)
//	{
//		ptr = p;
//	}
//	free(ptr);
//	ptr = NULL;
//		return 0;
//}

